<?php
declare(strict_types=1);

namespace app\service;

use app\model\{ExpressServiceProvider, ExpressPriceCache};
use think\facade\Cache;

class ExpressPriceService
{
    /**
     * 计算快递费用
     * @param string $serviceCode 服务商代码
     * @param string $fromProvince 寄件省份
     * @param string $fromCity 寄件城市
     * @param string $toProvince 收件省份
     * @param string $toCity 收件城市
     * @param float $weight 重量(kg)
     * @param float $volume 体积(m³)
     * @return array
     */
    public function calculate(
        string $serviceCode,
        string $fromProvince,
        string $fromCity,
        string $toProvince,
        string $toCity,
        float $weight,
        float $volume = 0
    ): array {
        try {
            // 获取服务商配置
            $provider = ExpressServiceProvider::where([
                'service_code' => $serviceCode,
                'status' => 1
            ])->find();
            
            if (!$provider) {
                throw new \Exception('快递服务商不存在或已禁用');
            }
            
            // 计算抛重
            $volumeWeight = $this->calculateVolumeWeight($volume, $provider->weight_index);
            $finalWeight = max($weight, $volumeWeight);
            
            // 获取价格缓存
            $price = $this->getPriceFromCache(
                $provider->id,
                $fromProvince,
                $fromCity,
                $toProvince,
                $toCity
            );
            
            if (!$price) {
                // 调用接口获取价格
                $price = $this->queryPrice(
                    $provider,
                    $fromProvince,
                    $fromCity,
                    $toProvince,
                    $toCity
                );
                
                // 缓存价格
                $this->cachePriceInfo(
                    $provider->id,
                    $fromProvince,
                    $fromCity,
                    $toProvince,
                    $toCity,
                    $price
                );
            }
            
            // 计算费用
            $fee = $this->calculateFee($finalWeight, $price['first_price'], $price['continued_price']);
            
            return [
                'weight' => $finalWeight,
                'first_price' => $price['first_price'],
                'continued_price' => $price['continued_price'],
                'total_fee' => $fee
            ];
        } catch (\Exception $e) {
            LogService::exception($e, [
                'service_code' => $serviceCode,
                'from_province' => $fromProvince,
                'from_city' => $fromCity,
                'to_province' => $toProvince,
                'to_city' => $toCity,
                'weight' => $weight,
                'volume' => $volume
            ]);
            throw $e;
        }
    }
    
    /**
     * 计算抛重
     * @param float $volume 体积(m³)
     * @param int $index 抛重系数
     * @return float
     */
    protected function calculateVolumeWeight(float $volume, int $index = 6000): float
    {
        if ($volume <= 0) {
            return 0;
        }
        return $volume * $index;
    }
    
    /**
     * 从缓存获取价格
     */
    protected function getPriceFromCache(
        int $providerId,
        string $fromProvince,
        string $fromCity,
        string $toProvince,
        string $toCity
    ): ?array {
        $cacheKey = sprintf(
            'express_price_%d_%s_%s_%s_%s',
            $providerId,
            md5($fromProvince . $fromCity),
            md5($toProvince . $toCity)
        );
        
        $data = Cache::get($cacheKey);
        if (!$data) {
            // 从数据库获取缓存
            $cache = ExpressPriceCache::where([
                'express_service_provider_id' => $providerId,
                'from_province' => $fromProvince,
                'from_city' => $fromCity,
                'to_province' => $toProvince,
                'to_city' => $toCity
            ])->find();
            
            if ($cache) {
                $data = [
                    'first_price' => $cache->first_price,
                    'continued_price' => $cache->continued_price
                ];
                Cache::set($cacheKey, $data, 3600);
            }
        }
        
        return $data;
    }
    
    /**
     * 缓存价格信息
     */
    protected function cachePriceInfo(
        int $providerId,
        string $fromProvince,
        string $fromCity,
        string $toProvince,
        string $toCity,
        array $price
    ): void {
        // 保存到数据库
        ExpressPriceCache::create([
            'express_service_provider_id' => $providerId,
            'from_province' => $fromProvince,
            'from_city' => $fromCity,
            'to_province' => $toProvince,
            'to_city' => $toCity,
            'first_price' => $price['first_price'],
            'continued_price' => $price['continued_price']
        ]);
        
        // 保存到缓存
        $cacheKey = sprintf(
            'express_price_%d_%s_%s_%s_%s',
            $providerId,
            md5($fromProvince . $fromCity),
            md5($toProvince . $toCity)
        );
        
        Cache::set($cacheKey, $price, 3600);
    }
    
    /**
     * 计算运费
     */
    protected function calculateFee(float $weight, float $firstPrice, float $continuedPrice): float
    {
        if ($weight <= 1) {
            return $firstPrice;
        }
        
        return $firstPrice + ceil($weight - 1) * $continuedPrice;
    }
    
    /**
     * 查询价格
     */
    protected function queryPrice(
        ExpressServiceProvider $provider,
        string $fromProvince,
        string $fromCity,
        string $toProvince,
        string $toCity
    ): array {
        // TODO: 实现服务商接口调用
        return [
            'first_price' => 0,
            'continued_price' => 0
        ];
    }
} 